LL_LPUART_Init and LL_LPUART_DeInit APIs migration

The LL initialization and de-initialization functions previously available in the stm32tnxx_ll_lpuart.c files within HAL1 are no longer present in HAL2. In HAL2, all LL C files ( stm32tnxx_ll_lpuart.c) have been removed, leaving only the LL header files ( stm32tnxx_ll_lpuart.h) that contain static inline functions.

If users need to initialize or de-initialize LPUART using the LL layer, they have two methods:

  • Utilize STM32CubeMX2 Code Generation: Rely on STM32CubeMX2 to generate code with the LL layer for LPUART initialization and de-initialization.

  • Replace manually the initialization and de-initialization functionsReplace the LL_LPUART_Init and LL_LPUART_DeInit functions

    manually with equivalent sequences using the static inline functions provided in the stm32tnxx_ll_lpuart.h file, tailored to their specific configuration and requirements.

This approach ensures that the initialization and de-initialization sequences are precisely addressing the given use case based on the LL static inline functions provided in the stm32tnxx_ll_lpuart.h header file. The sequences offer improved footprint optimization compared to the previous LL initialization functions found in stm32tnxx_ll_lpuart.c.

Related concept: Remove stm32tnxx_ll_ppp.c files

Method 1: Utilize STM32CubeMX2 Code Generation

LL LPUART configuration panel

  • Create a new project with the STM32CubeMX2, then start the initialization and the main configuration.

  • Choose the LL layer for code generation.

ll project configuration panel

LL LPUART main features configuration

Configure the LPUART main features.

LPUART main feature configuration

LL LPUART advanced features configuration

Configure the LPUART advanced features.

LPUART advanced feature configuration

LL GPIO configuration

Configure the LPUART_TX and the LPUART_RX GPIO pins.

GPIO TX configuration

LPUART GPIO TX configuration

GPIO RX configuration

LPUART GPIO RX configuration

LL DMA configuration

Configure the DMA for data reception as needed.

DMA TX configuration

LPUART DMA TX configuration

DMA RX configuration

LPUART DMA RX configuration

LL NVIC configuration

Configure the NVIC in case of an interrupt.

LPUART NVIC configuration

Generated LPUART initialization sequence

The LPUART initialization sequences is generated in the mx_lpuart1_uart_init and mx_lpuart1_uart_deinit functions in mx_lpuart1.c file under $YOUR_PROJECT_NAME$/$YOUR_PROJECT_NAME$_SW/generated/STM32Cube_CodeGen.

STM32CubeMX2 Generated : USART initialization sequence

Topic

Code Snippet HAL1

Code Snippet HAL2

Initialization and configuration sequence

static void MX_LPUART1_UART_Init(void)
{
  LL_LPUART_InitTypeDef LPUART_InitStruct = {0};

  LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};

  /** Initializes the peripherals clock */
  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_LPUART1;
  PeriphClkInit.Lpuart1ClockSelection = RCC_LPUART1CLKSOURCE_PCLK3;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  {
    Error_Handler();
  }

  /* Peripheral clock enable */
  LL_APB3_GRP1_EnableClock(LL_APB3_GRP1_PERIPH_LPUART1);

  LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOC);

  GPIO_InitStruct.Pin = LL_GPIO_PIN_0|LL_GPIO_PIN_1;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
  GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
  GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
  GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
  GPIO_InitStruct.Alternate = LL_GPIO_AF_8;
  LL_GPIO_Init(GPIOC, &GPIO_InitStruct);

  /* LPUART1 interrupt Init */
  NVIC_SetPriority(LPUART1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
  NVIC_EnableIRQ(LPUART1_IRQn);

  LPUART_InitStruct.PrescalerValue = LL_LPUART_PRESCALER_DIV1;
  LPUART_InitStruct.BaudRate = 209700;
  LPUART_InitStruct.DataWidth = LL_LPUART_DATAWIDTH_8B;
  LPUART_InitStruct.StopBits = LL_LPUART_STOPBITS_1;
  LPUART_InitStruct.Parity = LL_LPUART_PARITY_NONE;
  LPUART_InitStruct.TransferDirection = LL_LPUART_DIRECTION_TX_RX;
  LPUART_InitStruct.HardwareFlowControl = LL_LPUART_HWCONTROL_NONE;
  LL_LPUART_Init(LPUART1, &LPUART_InitStruct);
  LL_LPUART_SetTXFIFOThreshold(LPUART1, LL_LPUART_FIFOTHRESHOLD_1_8);
  LL_LPUART_SetRXFIFOThreshold(LPUART1, LL_LPUART_FIFOTHRESHOLD_1_8);
  LL_LPUART_DisableFIFO(LPUART1);
  LL_LPUART_Enable(LPUART1);

}

static void MX_GPIO_Init(void)
{
  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOC_CLK_ENABLE();
}
USART_TypeDef *mx_lpuart1_uart_init(void)
{
  uint32_t reg_temp;

  LL_APB3_GRP1_EnableClock(LL_APB3_GRP1_PERIPH_LPUART1);

  LL_RCC_SetLPUARTClockSource(LL_RCC_LPUART1_CLKSOURCE_PCLK3);

  LL_USART_ConfigAsyncMode(LPUART1);

  reg_temp = (LL_USART_DATAWIDTH_8_BIT | LL_USART_PARITY_NONE
              | LL_USART_DIRECTION_TX_RX | LL_USART_OVERSAMPLING_16);
  LL_LPUART_ConfigXfer(LPUART1, reg_temp, LL_USART_STOP_BIT_1);

  LL_USART_SetHWFlowCtrl(LPUART1, LL_USART_HWCONTROL_NONE);

  LL_USART_SetPrescaler(LPUART1, LL_USART_PRESCALER_DIV1);

  LL_LPUART_SetBaudRate(LPUART1, 48000000, LL_USART_PRESCALER_DIV1, 115200);

  /* Overrun configuration */
  LL_USART_DisableOverrunDetect(LPUART1);

  /* GPIO Clocks activation */
  LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOA);

  /* Configure IO output speed (Low, Medium, High or Very-High) */
  LL_GPIO_SetPinSpeed(GPIOA, LL_GPIO_PIN_10, LL_GPIO_SPEED_FREQ_LOW);
  LL_GPIO_SetPinSpeed(GPIOA, LL_GPIO_PIN_3, LL_GPIO_SPEED_FREQ_LOW);

  /* Configure IO output type (Push-Pull or Open-Drain) */
  LL_GPIO_SetPinOutputType(GPIOA, LL_GPIO_PIN_10 | LL_GPIO_PIN_3, LL_GPIO_OUTPUT_PUSHPULL);

  /* Activate the Pull-up, Pull-down resistor, or No pull for the current IO */
  LL_GPIO_SetPinPull(GPIOA, LL_GPIO_PIN_10, LL_GPIO_PULL_NO);
  LL_GPIO_SetPinPull(GPIOA, LL_GPIO_PIN_3, LL_GPIO_PULL_NO);

  /* Configure the Alternate Function in current IO */
  LL_GPIO_SetAFPin_8_15(GPIOA, LL_GPIO_PIN_10, LL_GPIO_AF_3);
  LL_GPIO_SetAFPin_0_7(GPIOA, LL_GPIO_PIN_3, LL_GPIO_AF_3);

  /* Configure IO direction mode (Input, Output, Alternate or Analog) */
  LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_10, LL_GPIO_MODE_ALTERNATE);
  LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_3, LL_GPIO_MODE_ALTERNATE);

  /* Enable interrupt */
  NVIC_SetPriority(LPUART1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0, 0));
  NVIC_EnableIRQ(LPUART1_IRQn);

  LL_USART_Enable(LPUART1);
  return LPUART1;
}

Deinitialization sequence

void MX_LPUART1_UART_DeInit(void)
{
  if (LL_LPUART_DeInit(LPUART1) != HAL_OK)
  {
    Error_Handler();
  }
}
void mx_lpuart1_uart_deinit(void)
{
  LL_APB3_GRP1_ForceReset(LL_APB3_GRP1_PERIPH_LPUART1);
  LL_APB3_GRP1_ReleaseReset(LL_APB3_GRP1_PERIPH_LPUART1);

  LL_APB3_GRP1_DisableClock(LL_APB3_GRP1_PERIPH_LPUART1);

  /* Disable interrupt */
  NVIC_DisableIRQ(LPUART1_IRQn);
  LL_USART_Disable(LPUART1);

  /* ### GPIO deinitialization of LPUART1: LPUART1_RX,LPUART1_TX ########################### */

  /* Configure IO in Analog Mode */
  LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_10, LL_GPIO_MODE_ANALOG);
  LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_3, LL_GPIO_MODE_ANALOG);

  /* Configure the default Alternate Function in current IO */
  LL_GPIO_SetAFPin_8_15(GPIOA, LL_GPIO_PIN_10, LL_GPIO_AF_0);
  LL_GPIO_SetAFPin_0_7(GPIOA, LL_GPIO_PIN_3, LL_GPIO_AF_0);

  /* Configure the default value for IO Speed */
  LL_GPIO_SetPinSpeed(GPIOA, LL_GPIO_PIN_10, LL_GPIO_SPEED_FREQ_LOW);
  LL_GPIO_SetPinSpeed(GPIOA, LL_GPIO_PIN_3, LL_GPIO_SPEED_FREQ_LOW);

  /* Configure the default value IO Output Type */
  LL_GPIO_SetPinOutputType(GPIOA, LL_GPIO_PIN_10 | LL_GPIO_PIN_3, LL_GPIO_OUTPUT_PUSHPULL);

  /* Deactivate the Pull-up and Pull-down resistor for the current IO */
  LL_GPIO_SetPinPull(GPIOA, LL_GPIO_PIN_10, LL_GPIO_PULL_NO);
  LL_GPIO_SetPinPull(GPIOA, LL_GPIO_PIN_3, LL_GPIO_PULL_NO);

  /* Reset the IO output state */
  LL_GPIO_WriteOutputPin(GPIOA, LL_GPIO_PIN_10 | LL_GPIO_PIN_3, LL_GPIO_PIN_RESET);
}

Method 2: Replace manually the initialization and de-initialization functions

LL_LPUART_Init() API migration

According to the use-case, implement the precise sequence call based on the LL static inline functions provided in the stm32tnxx_ll_lpuart.h header file.

HAL1

HAL2

Case when kernel clock source is unknown:

LL_LPUART_InitTypeDef LPUART_InitStruct;

LPUART_InitStruct->BaudRate            = 115200;


LPUART_InitStruct->DataWidth           = LL_LPUART_DATAWIDTH_8B;
LPUART_InitStruct->StopBits            = LL_LPUART_STOPBITS_1;
LPUART_InitStruct->Parity              = LL_LPUART_PARITY_NONE;
LPUART_InitStruct->TransferDirection   = LL_LPUART_DIRECTION_TX_RX;
LPUART_InitStruct->HardwareFlowControl = LL_LPUART_HWCONTROL_NONE;
LPUART_InitStruct->PrescalerValue      = LL_LPUART_PRESCALER_DIV1;

LL_LPUART_Init(LPUART1, &LPUART_InitStruct);
uint32_t instance_clock_freq;


instance_clock_freq = HAL_RCC_LPUART1_GetKernelClkFreq();
LL_LPUART_SetBaudRate(LPUART1, instance_clock_freq, LL_LPUART_PRESCALER_DIV1, 115200);

LL_LPUART_SetDataWidth(LPUART1, LL_LPUART_DATAWIDTH_8_BIT);
LL_LPUART_SetStopBitsLength(LPUART1, LL_LPUART_STOP_BIT_1);
LL_LPUART_SetParity(LPUART1, LL_LPUART_PARITY_NONE);
LL_LPUART_SetTransferDirection(LPUART1, LL_LPUART_DIRECTION_TX_RX);
LL_LPUART_SetHWFlowCtrl(LPUART1, LL_LPUART_HWCONTROL_NONE);
LL_LPUART_SetPrescaler(LPUART1, LL_LPUART_PRESCALER_DIV1);

Case when kernel clock frequency is known:

LL_LPUART_InitTypeDef LPUART_InitStruct;

LPUART_InitStruct->BaudRate            = 115200;

LPUART_InitStruct->DataWidth           = LL_LPUART_DATAWIDTH_8B;
LPUART_InitStruct->StopBits            = LL_LPUART_STOPBITS_1;
LPUART_InitStruct->Parity              = LL_LPUART_PARITY_NONE;
LPUART_InitStruct->TransferDirection   = LL_LPUART_DIRECTION_TX_RX;
LPUART_InitStruct->HardwareFlowControl = LL_LPUART_HWCONTROL_NONE;
LPUART_InitStruct->PrescalerValue      = LL_LPUART_PRESCALER_DIV1;

LL_LPUART_Init(LPUART1, &LPUART_InitStruct);
/* */

uint32_t instance_clock_freq = 48000000;
LL_LPUART_SetBaudRate(LPUART1, instance_clock_freq, LL_LPUART_PRESCALER_DIV1, 115200);

LL_LPUART_SetDataWidth(LPUART1, LL_LPUART_DATAWIDTH_8_BIT);
LL_LPUART_SetStopBitsLength(LPUART1, LL_LPUART_STOP_BIT_1);
LL_LPUART_SetParity(LPUART1, LL_LPUART_PARITY_NONE);
LL_LPUART_SetTransferDirection(LPUART1, LL_LPUART_DIRECTION_TX_RX);
LL_LPUART_SetHWFlowCtrl(LPUART1, LL_LPUART_HWCONTROL_NONE);
LL_LPUART_SetPrescaler(LPUART1, LL_LPUART_PRESCALER_DIV1);

LL_LPUART_DeInit() API Migration

According to the used LPUART instance, implement the precise calls to LL_APB3_GRP1_ForceReset() and LL_APB3_GRP1_ReleaseReset().

Example: The application is using LPUART1

Comparison of HAL1 and HAL2

HAL1

HAL2

LL_LPUART_DeInit(LPUART1);
LL_APB3_GRP1_ForceReset(LL_APB3_GRP1_PERIPH_LPUART1);
LL_APB3_GRP1_ReleaseReset(LL_APB3_GRP1_PERIPH_LPUART1);